using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Per.Common;
using UnityEngine;
using UnityEngine.Networking;

namespace Unity.Per.Common.WebRPC {

    public abstract class BaseWebRPC
    {
        public string url;
        public string kHttpVerb;
        public bool AddToken = false;
        public Action<BaseWebRPC, bool ,Respond> finishcallback;

        private List<IMultipartFormSection> formData;
        private Dictionary<string,string> simpleformData;
        private Dictionary<string, string> headerData;

        public const string Authorization = "Authorization";

        private string host {
            get {
                try {
                    return new Uri(url).Host;
                } catch {
                    return "";
                }
            }
        }

        //Only for Use StartCoroutine API
        //--------------
        private webRTCRun webRTCMono;
        class webRTCRun :MonoBehaviour { }
        Coroutine doRPC;
        //--------------

        //Only for get Token
        class TokenType
        {
            public string token;
            public string Token;
        }

        public class Respond {
            public int status;
            public string message;
            public List<string> result;
        }

        public BaseWebRPC(string url,string kHttpVerb,bool AddToken=true) {
            this.url = url;
            this.kHttpVerb = kHttpVerb;
            this.AddToken = AddToken;
            formData = new List<IMultipartFormSection>();
            simpleformData = new Dictionary<string, string>();
            headerData = new Dictionary<string, string>();
            doRPC = null;
            webRTCMono = new GameObject("WebRPC").AddComponent<webRTCRun>();
        }

        ~BaseWebRPC() {
            if ( doRPC != null ) {
                webRTCMono.StopCoroutine(doRPC);
                doRPC = null;
            }
            UnityEngine.Object.DestroyImmediate(webRTCMono.gameObject);
            webRTCMono = null;
            formData = null;
            simpleformData = null;
            headerData = null;
        }

        public void Do() {
            if ( doRPC == null ) {
                doRPC = webRTCMono.StartCoroutine(dowebRPC());
            } else {
                DebugMy.Log("RPC donot finish Can not Do again!", this, true);
            }
        }

        public void Kill() {
            if ( doRPC != null ) {
                webRTCMono.StopCoroutine(dowebRPC());
                doRPC = null;
            }
        }

        protected virtual IEnumerator dowebRPC() {
            if ( url == "" ) {
                DebugMy.Log(@"UnityWebRequest url=""  ERROR", this, true);
                yield break;

            }
            if (
                kHttpVerb != UnityWebRequest.kHttpVerbGET &&
                kHttpVerb != UnityWebRequest.kHttpVerbHEAD &&
                kHttpVerb != UnityWebRequest.kHttpVerbPOST &&
                kHttpVerb != UnityWebRequest.kHttpVerbPUT &&
                kHttpVerb != UnityWebRequest.kHttpVerbPOST &&
                kHttpVerb != UnityWebRequest.kHttpVerbCREATE &&
                kHttpVerb != UnityWebRequest.kHttpVerbDELETE
                ) {
                DebugMy.Log(@"UnityWebRequest kHttpVerb=" + kHttpVerb + "  ERROR", this, true);
                yield break;
            }

            {
                UnityWebRequest www;

                if ( formData.Count > 0 ) {
                    www = UnityWebRequest.Post(url, formData);
                } else if (simpleformData.Count>0) {
                    www = UnityWebRequest.Post(url, simpleformData);
                } else {
                    www = new UnityWebRequest(url, kHttpVerb);
                }
                using ( www ) {
                    if ( headerData != null ) {
                        foreach ( var header in headerData ) {
                            www.SetRequestHeader(header.Key, header.Value);
                        }
                    }

                    //www.SetRequestHeader("Content-Type", "application/multipart/form-data");
                    if ( AddToken ) {
                        SetHeader("Authorization", PlayerPrefs.GetString(host));
                    }
                    AddDownloadHander(www);
                    AddUploadHander(www);

                    yield return www.SendWebRequest();

                    if ( www.result == UnityWebRequest.Result.Success ) {

                        if ( host != "" ) {
                            string text = www.downloadHandler.text;
                            TokenType token = JsonUtility.FromJson<TokenType>(text);
                            if ( token.token != null ) {
                                PlayerPrefs.SetString(host, token.token);
                                DebugMy.Log("Storetoken:" + host + "=" + token.token, this, true);
                            }
                            if ( token.Token != null ) {
                                PlayerPrefs.SetString(host, token.Token);
                                DebugMy.Log("StoreToken:" + host + "=" + token.token, this, true);
                            }
                        }

                        Respond res = JsonUtility.FromJson<Respond>(www.downloadHandler.text);

                        if ( finishcallback != null )
                            finishcallback(this,true, res);

                        //Debug.Log("File successfully downloaded and saved to " + www.result);
                    } else {

                        Respond res = new Respond();
                        res.status = -1;
                        res.message = www.result.ToString();
                        res.result = null;

                        PostProcess(www);

                        if ( finishcallback != null )
                            finishcallback(this,false, res);
                    }


                }

            }

        }

        protected virtual void AddDownloadHander(UnityWebRequest www) {

        }

        protected virtual void AddUploadHander(UnityWebRequest www) {

        }

        protected virtual void PostProcess(UnityWebRequest www) { 
        
        }

        public void SetHeader(string name, string value) {
            if ( name == "" || value == "" ) {
                return;
            }
            if ( headerData == null ) {
                headerData = new Dictionary<string, string>();
            }
            if ( headerData.ContainsKey(name) ) {
                headerData[name] = value;
            } else {
                headerData.Add(name, value);
            }
        }

        public void SetForm(string name,string value) {
            if ( name == "" || value == "" ) {
                return;
            }
            if ( simpleformData == null ) {
                simpleformData = new Dictionary<string, string>();
            }
            simpleformData.Add(name,value);
        }

        public void SetForm(IMultipartFormSection form) {
            if ( form == null ) {
                return;
            }
            if ( formData == null ) {
                formData = new List<IMultipartFormSection>();
            }
            formData.Add(form);
        }
        public void SetForm(List<IMultipartFormSection> formlist) {
            if ( formlist == null ) {
                return;
            }
            if ( formData == null ) {
                formData = new List<IMultipartFormSection>();
            }
            formData.AddRange(formlist);
        }

    }

}